package perf.cli;

import java.io.File;
import java.io.FileNotFoundException;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;


public class CommandLineInterface {

	private Executor executor;
	private Options opts;
	private CommandLine cli;
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		CommandLineInterface manager = new CommandLineInterface( );
		
		try {
			
			manager.run( args );
			
		} catch (ParseException pe) {
			System.err.println( pe.getMessage() );
			manager.printHelp( );
			//pe.printStackTrace( System.err );
		}
	}
	
	public CommandLineInterface( ) {
		executor = new Executor( );
		opts = AppOpts.getOptions();
	}
	
	public void run( String[] args ) throws ParseException {
		cli = (new PosixParser()).parse( opts, args );
		
		loadDb();

		if (cli.hasOption( AppOpts.HELP.shortOpt() ) ) {
			printHelp( );
		} else if ( cli.hasOption( AppOpts.LIST_RUN.shortOpt() ) ) {
			executor.listRun( parseIndex( AppOpts.CHOOSE_SETUP ) );
		} else if ( cli.hasOption( AppOpts.ADD_RUN.shortOpt() ) ) {
			addRun( );
		} else if ( cli.hasOption( AppOpts.REMOVE_RUN.shortOpt() ) ) {
			removeRun( );
		} else if ( cli.hasOption( AppOpts.ADD_SETUP.shortOpt() ) ) {
			executor.addSetup( parseName( AppOpts.ADD_SETUP ) );
		} else if ( cli.hasOption( AppOpts.LIST_SETUP.shortOpt() ) ) {
			executor.listSetup();
		} else if ( cli.hasOption( AppOpts.REMOVE_SETUP.shortOpt() ) ) {
			executor.removeSetup( parseIndex( AppOpts.CHOOSE_SETUP ) );
		} else if ( cli.hasOption( AppOpts.TEXT_DUMP.shortOpt() ) ) {
			executor.dump();
 		} else {
			System.out.println( "no options specified" );
			printHelp();
		}
		
		executor.close();
	}
	
	private void addRun( ) throws ParseException {
		File f = new File( cli.getOptionValue( AppOpts.ADD_RUN.shortOpt() ) );
		
		try {
			executor.addRun( f, parseIndex( AppOpts.CHOOSE_SETUP) );
		} catch (FileNotFoundException fnfe) {
			throw new ParseException( "File not found: " + f );
		}
	}
	
	private void removeRun( ) throws ParseException {
		try {
			executor.removeRun( 
					parseIndex( AppOpts.REMOVE_RUN ), 
					parseIndex( AppOpts.CHOOSE_SETUP ) );
			
		} catch (IndexOutOfBoundsException ioobe) {
			System.out.println( "Error: Non existent index!" );
		}
	}
	
	private void loadDb( ) throws ParseException {
		File db;
		if ( ! cli.hasOption( AppOpts.DATA_BASE.shortOpt() ) ) {
			
			//if there's only one file in the working directory
			//ending with db, then try to use it.
			File curDir = new File( System.getProperty("user.dir") );
			File[] files = curDir.listFiles( new DbFileFilter() );
			if ( files.length != 1) {
				throw new ParseException( "Missing -d parameter. " 
						+ "The database to use has to be specified" );
			}
			db = files[0];
		} else {
			db = new File( cli.getOptionValue( AppOpts.DATA_BASE.shortOpt() ) );
		}
		
		executor.startDb( db );
	}
	
	private String parseName( AppOpts opt ) throws ParseException {
		if ( cli.hasOption( opt.shortOpt() ) ) {
			String name = cli.getOptionValue( opt.shortOpt() );
			if ( name != null ) {
				return name;
			}
		}
		throw new ParseException( "-" + opt.shortOpt() + " option has to be specified" );
	}
	
	private int parseIndex( AppOpts opt) throws ParseException {
		int index;
		String val = cli.getOptionValue( opt.shortOpt() );
		
		if ( val != null) {
			try {
				index = Integer.parseInt( val );
			} catch (NumberFormatException nfe) {
				throw new ParseException( "Invalid index, it has to be an integer" );
			}
		} else {
			throw new ParseException( "Missing index option" );
		}
		
		return index;
	}
	
	private void printHelp( ) {
		HelpFormatter hf = new HelpFormatter( );
		hf.printHelp( "PerfEct", opts );
		
	}
}
